/*
 ### jQuery XML to JSON Plugin v1.3 - 2013-02-18 ###
 * http://www.fyneworks.com/ - diego@fyneworks.com
	* Licensed under http://en.wikipedia.org/wiki/MIT_License
 ###
 Website: http://www.fyneworks.com/jquery/xml-to-json/
*//*
 # INSPIRED BY: http://www.terracoder.com/
           AND: http://www.thomasfrank.se/xml_to_json.html
											AND: http://www.kawa.net/works/js/xml/objtree-e.html
*//*
 This simple script converts XML (document of code) into a JSON object. It is the combination of 2
 'xml to json' great parsers (see below) which allows for both 'simple' and 'extended' parsing modes.
*/
// Avoid collisions
;if(window.jQuery) (function($){
 
 // Add function to jQuery namespace
 $.extend({
  
  // converts xml documents and xml text to json object
  xml2json: function(xml, extended) {
	  if(!xml) return {}; // quick fail
   
	  //### PARSER LIBRARY
	  // Core function
	  function parseXML(node, simple){
		  if(!node) return null;
		  var txt = '', obj = null, att = null;
		  var nt = node.nodeType, nn = jsVar(node.localName || node.nodeName);
		  var nv = node.text || node.nodeValue || '';
		  /*DBG*/ //if(window.console) console.log(['x2j',nn,nt,nv.length+' bytes']);
		  if(node.childNodes){
			  if(node.childNodes.length>0){
				  /*DBG*/ //if(window.console) console.log(['x2j',nn,'CHILDREN',node.childNodes]);
				  $.each(node.childNodes, function(n,cn){
					  var cnt = cn.nodeType, cnn = jsVar(cn.localName || cn.nodeName);
					  var cnv = cn.text || cn.nodeValue || '';
					  /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>a',cnn,cnt,cnv]);
					  if(cnt == 8){
						  /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>b',cnn,'COMMENT (ignore)']);
						  return; // ignore comment node
					  }
					  else if(cnt == 3 || cnt == 4 || !cnn){
						  // 	ignore white-space in between tags
						  if(cnv.match(/^\s+$/)){
							  /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>c',cnn,'WHITE-SPACE (ignore)']);
							  return;
						  };
						  /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>d',cnn,'TEXT']);
						  txt += cnv.replace(/^\s+/,'').replace(/\s+$/,'');
								// make sure we ditch trailing spaces from markup
					  }
					  else{
						  /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>e',cnn,'OBJECT']);
						  obj = obj || {};
						  if(obj[cnn]){
							  /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>f',cnn,'ARRAY']);
							  // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child
							  if(!obj[cnn].length) obj[cnn] = myArr(obj[cnn]);
							  obj[cnn] = myArr(obj[cnn]);
							  obj[cnn][ obj[cnn].length ] = parseXML(cn, true/* simple */);
							  obj[cnn].length = obj[cnn].length;
						  }
						  else{
							  /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>g',cnn,'dig deeper...']);
							  obj[cnn] = parseXML(cn);
						  };
					  };
				  });
			  };//node.childNodes.length>0
		  };//node.childNodes
    
		  if(node.attributes){
			  if(node.attributes.length>0){
				  /*DBG*/ //if(window.console) console.log(['x2j',nn,'ATTRIBUTES',node.attributes])
				  att = {}; obj = obj || {};
				  $.each(node.attributes, function(a,at){
					  var atn = '@'+jsVar(at.name), atv = at.value;
					  att[atn] = atv;
					  if(obj[atn]){
						  /*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'ARRAY']);
						  // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child
						  //if(!obj[atn].length) obj[atn] = myArr(obj[atn]);//[ obj[ atn ] ];
						  obj[atn] = myArr(obj[atn]);
						  obj[atn][ obj[atn].length ] = atv;
						  obj[atn].length = obj[atn].length;
					  }
					  else{
						  /*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'TEXT']);
						  obj[atn] = atv;
					  };
				  });
				  //	obj['attributes'] = att;
			  };//node.attributes.length>0
		  };//node.attributes
		  if(obj){
			  obj = $.extend( (txt!='' ? new String(txt) : {}),/* {text:txt},*/ obj || {}/*, att || {}*/);
			  //	txt = (obj.text) ? (typeof(obj.text)=='object' ? obj.text : [obj.text || '']).concat([txt]) : txt;
			  txt = (obj.text) ? ([obj.text || '']).concat([txt]) : txt;
			  if(txt) obj.text = txt;
			  txt = '';
		  };
		  var out = obj || txt;
		  //	console.log([extended, simple, out]);
		  if(extended){
			  if(txt) out = {};//new String(out);
			  txt = out.text || txt || '';
			  if(txt) out.text = txt;
			  if(!simple) out = myArr(out);
		  };
		  return out;
	  };// parseXML
	  // Core Function End
	  // Utility functions
	  var jsVar = function(s){ return String(s || '').replace(/-/g,"_"); };
   
	  // NEW isNum function: 01/09/2010
	  // Thanks to Emile Grau, GigaTecnologies S.L., www.gigatransfer.com, www.mygigamail.com
	  function isNum(s){
		  // based on utility function isNum from xml2json plugin (http://www.fyneworks.com/ - diego@fyneworks.com)
		  // few bugs corrected from original function :
		  // - syntax error : regexp.test(string) instead of string.test(reg)
		  // - regexp modified to accept  comma as decimal mark (latin syntax : 25,24 )
		  // - regexp modified to reject if no number before decimal mark  : ".7" is not accepted
		  // - string is "trimmed", allowing to accept space at the beginning and end of string
		  var regexp=/^((-)?([0-9]+)(([\.\,]{0,1})([0-9]+))?$)/
		  return (typeof s == "number") || regexp.test(String((s && typeof s == "string") ? jQuery.trim(s) : ''));
	  };
	  // 	OLD isNum function: (for reference only)
	  //var isNum = function(s){ return (typeof s == "number") || String((s && typeof s == "string") ? s : '').test(/^((-)?([0-9]*)((\.{0,1})([0-9]+))?$)/); };
																
	  var myArr = function(o){
		  
		  // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child
		  //if(!o.length) o = [ o ]; o.length=o.length;
		  if(!$.isArray(o)) o = [ o ]; o.length=o.length;
		  // here is where you can attach additional functionality, such as searching and sorting...
		  return o;
	  };
	  // Utility functions End
	  //	### PARSER LIBRARY END
	  
	  // Convert plain text to xml
	  if(typeof xml=='string') xml = $.text2xml(xml);
   
	  // Quick fail if not xml (or if this is a node)
	  if(!xml.nodeType) return;
	  if(xml.nodeType == 3 || xml.nodeType == 4) return xml.nodeValue;
   
	  // Find xml root node
	  var root = (xml.nodeType == 9) ? xml.documentElement : xml;
   
	  // Convert xml to json
	  var out = parseXML(root, true /* simple */);
   
	  // 	Clean-up memory
	  xml = null; root = null;
   
	  // Send output
	  return out;
  	},
  
  	// 	Convert text to XML DOM
  text2xml: function(str) {
   // NOTE: I'd like to use jQuery for this, but jQuery makes all tags uppercase
   //return $(xml)[0];
   
   /* prior to jquery 1.9 */
   /*
   var out;
   try{
    var xml = ((!$.support.opacity && !$.support.style))?new ActiveXObject("Microsoft.XMLDOM"):new DOMParser();
    xml.async = false;
   }catch(e){ throw new Error("XML Parser could not be instantiated") };
   try{
    if((!$.support.opacity && !$.support.style)) out = (xml.loadXML(str))?xml:false;
    else out = xml.parseFromString(str, "text/xml");
   }catch(e){ throw new Error("Error parsing XML string") };
   return out;
   */

   /* jquery 1.9+ */
   return $.parseXML(str);
  }
		
 }); // extend $

})(jQuery);
